/*
 * Copyright 2008 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */


package com.db4o.groovy;

import com.db4o.DatabaseFileLockedException;
import com.db4o.DatabaseReadOnlyException;
import com.db4o.Db4o;
import com.db4o.Db4oIOException;
import com.db4o.IncompatibleFileFormatException;
import com.db4o.InvalidPasswordException;
import com.db4o.ObjectContainer;
import com.db4o.ObjectSet;
import com.db4o.config.ConfigScope;
import com.db4o.config.Configuration;
import com.db4o.config.FreespaceConfiguration;
import com.db4o.config.QueryConfiguration;
import com.db4o.diagnostic.DiagnosticConfiguration;
import com.db4o.ext.OldFormatException;
import com.db4o.io.IoAdapter;
import com.db4o.query.Constraint;
import com.db4o.query.Query;
import com.db4o.reflect.Reflector;
import com.spaceprogram.db4o.sql.ObjectSetWrapper;
import com.spaceprogram.db4o.sql.Sql4o;
import com.spaceprogram.db4o.sql.Sql4oException;
import com.spaceprogram.db4o.sql.parser.SqlParseException;

import java.io.PrintStream;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Map;

/**
 * Implemenation of groovy builder that supports
 * handling of db4o databases.
 *
 * @author klevgert
 */
public class Db4oBuilder extends groovy.util.BuilderSupport {
  
  public static final String HOST = "host";
  public static final String NAME = "name";
  public static final String USER = "user";
  public static final String PASSWORD = "password";
  public static final String PORT = "port";
  public static final String WAIT = "wait";
  public static final int DEFAULT_SEMAPHORE_WAIT = 1000;

  /** db4o configuration */
  private Configuration config;

  /** Opened db4o database container */
  private ObjectContainer objectContainer;

  /** Db4o object set holding query results */
  private ObjectSet objectSet;

  /** Holds a flat list of nodes created by this builder */
  private Map<Object,Db4oBuilderItem> nodeMap = new HashMap<Object,Db4oBuilderItem>();

  /** Holds the root query in case queries are nested */
  private Object rootNode;
  
  private String semaphoreName = "SEMAPHORE#1";
  private boolean semaphoreSet = false;

  private static class Nodes {
    public static final String AND = "and";
    public static final String CLIENT = "client";
    public static final String CONSTRAIN = "constrain";
    public static final String CONTAINS = "contains";
    public static final String DELETE = "delete";
    public static final String DESCEND = "descend";
    public static final String ENDSWITH = "endsWith";
    public static final String EQUAL = "equal";
    public static final String FILE = "file";
    public static final String GREATER = "greater";
    public static final String IDENTITY = "identity";
    public static final String LIKE = "like";
    public static final String NOT = "not";
    public static final String OR = "or";
    public static final String ORDER_ASCENDING = "orderAscending";
    public static final String ORDER_DESCENDING = "orderDescending";
    public static final String QUERY = "query";
    public static final String SEMAPHORE = "semaphore";
    public static final String SET = "set";
    public static final String SMALLER = "smaller";
    public static final String SQLQUERY = "sqlquery";
    public static final String STARTSWITH = "startsWith";
    public static final String CONFIG = "configuration";
  }
  
  private static class Config {
	public static final String ACTIVATION_DEPTH = "activationDepth";
	public static final String ALLOW_VERSION_UPDATE = "allowVersionUpdate";
	public static final String AUTOMATIC_SHUTDOWN = "automaticShutdown";
	public static final String BLOCK_SIZE = "blockSize";
	public static final String BTREE_CACHE_HEIGHT = "bTreeCacheHeight";
	public static final String BTREE_NODE_SIZE = "bTreeNodeSize";
	public static final String CALLBACKS = "callbacks";
	public static final String CALL_CONSTRUCTORS = "callConstructors";
	public static final String DETECT_SCHEMA_CHANGES = "detectSchemaChanges";
	public static final String EXCEPTION_ON_NOT_STORABLE = "exceptionsOnNotStorable";
	public static final String FLUSH_FILE_BUFFERS = "flushFileBuffers";
	public static final String GENERATE_UUIDS = "generateUUIDs";
	public static final String GENERATE_VERSION_NUMBERS = "generateVersionNumbers";
	public static final String INTERN_STRINGS = "internStrings";
	public static final String IO_ADAPTER = "io";
	public static final String LOCK_DATABASE_FILE = "lockDatabaseFile";
	public static final String MARK_TRANSIENT = "markTransient";
	public static final String MESSAGE_LEVEL = "messageLevel";
	public static final String OPTIMIZE_NATIVEQUERIES = "optimizeNativeQueries";
	public static final String REFLECT_WITH = "reflectWith";
	public static final String UNICODE = "unicode";
	public static final String UPDATE_DEPTH = "updateDepth";
	public static final String SET_OUT = "out";
  }

  /**
   * Supporting class to hold the data for a Db4o node
   * produced by a Db4o builder.
   */
  class Db4oBuilderItem {
    Object node;
    Object parent;
    Object value;
    Object object;

    Db4oBuilderItem(Object node) {
      this.node = node;
    }
    Db4oBuilderItem(Object node, Object value) {
      this.node = node;
      this.value = value;
    }
  }

  /**
   * Gets the object container opened
   * @return the db4o object container opened during building th nodes
   */
  public ObjectContainer getObjectContainer() {
    return objectContainer;
  }

  /**
   * Gets the object set that is a result when using
   * queries both based on sql or SODA.
   * @return db4o object set that takes the result of queries.
   */
  public ObjectSet getObjectSet() {
    return objectSet;
  }

  /**
   * Gets the object set that is a result set when using
   * queries both based on sql or SODA.
   * @return db4o object set that takes the result of queries.
   */
  public ObjectSet getResultSet() {
    return objectSet;
  }

  /**
   * Get the name of the semaphore if one has been set
   * @return name of a semaphore set
   */
  public String getSemaphoreName() {
    return semaphoreName;
  }

  /**
   * flag if the semaphore has been set successfully or not.
   * @return true if semaphore is set, otherwise false
   */
  public boolean isSemaphoreSet() {
    return semaphoreSet;
  }
  
  @Override
  protected Object createNode(Object node) {

    try{
      // first create and record a node
      this.nodeMap.put(node, new Db4oBuilderItem(node));

      // Take special action depending on the node type
      onCreateNode(node);
      
    } catch(Exception exc) {
      if( this.objectContainer != null) {
        this.objectContainer.close();
      }
    } 
    return node;
  }

  @Override
  protected Object createNode(Object node, Object value) {

    try{

      // first create and record a node
      this.nodeMap.put(node, new Db4oBuilderItem(node, value));

      // detect node type to start a special action
      // associated with the node.
      onCreateNode(node, value);

    } catch(Exception exc) {
      if( this.objectContainer != null) {
        this.objectContainer.close();
      }
    }

    return node;
  }

  @Override
  protected Object createNode(Object node, Map map) {
    try {

      this.nodeMap.put(node, new Db4oBuilderItem(node,map));

      onCreateNode(node, map);

    } catch(Exception exc) {
      if( this.objectContainer != null) {
        this.objectContainer.close();
      }
    }
    
    return node;
  }

  @Override
  protected Object createNode(Object node, Map map, Object value) {
    this.nodeMap.put(node, new Db4oBuilderItem(node));
    throw new UnsupportedOperationException();
  }

  @Override
  protected void setParent(Object parent, Object node) {
    
    // Post Create processing: associate node with its parent node
    if( this.nodeMap.containsKey(node) ) {
      Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
      if( item != null ) {
        item.parent = parent;
      }
    }

    onSetParent(node, parent);
  }

  @Override
  protected void nodeCompleted(Object parent, Object node) {
    onNodeCompleted(node);
  }

  protected void onCreateNode(Object node)  {
    
    if( node.equals(Nodes.QUERY) ) {
      this.rootNode = node;
      querySODA(node);
    } else if( node.equals(Nodes.SEMAPHORE) ) {
      String generatedName = GregorianCalendar.getInstance().getTime().toString();
      setSemaphore( generatedName  );
    } else if (node.equals(Nodes.CONFIG)) {
      setConfig();
    }
  }

  protected void onCreateNode(Object node, Object value)  {

    if (node.equals(Nodes.FILE)) {
      openFile(value.toString());
    } else if (node.equals(Nodes.CLIENT)) {
    } else if (node.equals(Nodes.SET)) {
      storeValue(value);
    } else if (node.equals(Nodes.DELETE)) {
      deleteValue(value);
    } else if (node.equals(Nodes.QUERY)) {
      this.rootNode = node;
      querySODA(node, value);
    } else if (node.equals(Nodes.SQLQUERY)) {
      querySQL((String) value);
    } else if (node.equals(Nodes.SEMAPHORE)) {
      setSemaphore((String) value);
    }
  }

  protected void onCreateNode(Object node, Map map)  {

    if (node.equals(Nodes.FILE)) {
      openFile(map);
    } else if (node.equals(Nodes.CLIENT)) {
      openClient(map);
    } else if (node.equals(Nodes.CONFIG)) {
      setConfig(map);
    } else if (node.equals(Nodes.SEMAPHORE)) {
      setSemaphore(map);
    }
  }

  protected void onSetParent(Object node, Object parent) {

    // Take special action after parent has been set
    if (node.equals(Nodes.DESCEND)) {
      addDescend(node, parent);
    } else if (node.equals(Nodes.CONSTRAIN)) {
      addConstrain(node, parent);
    } else if (node.equals(Nodes.GREATER)) {
      addGreater(node, parent);
    } else if (node.equals(Nodes.SMALLER)) {
      addSmaller(node, parent);
    } else if (node.equals(Nodes.NOT)) {
      addNot(node, parent);
    } else if (node.equals(Nodes.EQUAL)) {
      addEqual(node, parent);
    } else if (node.equals(Nodes.LIKE)) {
      addLike(node, parent);
    } else if (node.equals(Nodes.CONTAINS)) {
      addContains(node, parent);
    } else if (node.equals(Nodes.IDENTITY)) {
      addIdentity(node, parent);
    } else if (node.equals(Nodes.STARTSWITH)) {
      addStartsWith(node, parent);
    } else if (node.equals(Nodes.ENDSWITH)) {
      addEndsWith(node, parent);
    } else if (node.equals(Nodes.ORDER_ASCENDING)) {
      addOrder(node, parent, true);
    } else if (node.equals(Nodes.ORDER_DESCENDING)) {
      addOrder(node, parent, false);
    }
  }

  protected void onNodeCompleted(Object node) {

    if (node.equals(Nodes.FILE) || node.equals(Nodes.CLIENT)) {
      closeContainer();
    } else if (node.equals(Nodes.QUERY)) {
      executeQuery(node);
    } else if (node.equals(Nodes.SEMAPHORE)) {
      releaseSemaphore();
    } else if (node.equals(Nodes.AND)) {
    } else if (node.equals(Nodes.OR)) {
    }

  }

  private void openFile(String fileName) throws OldFormatException, DatabaseReadOnlyException, DatabaseFileLockedException, Db4oIOException, IncompatibleFileFormatException {
    this.objectContainer = Db4o.openFile(fileName);
  }

  private void openFile(Map map) throws OldFormatException, Db4oIOException, DatabaseReadOnlyException, IncompatibleFileFormatException, DatabaseFileLockedException {
    String fileName = map.get(NAME).toString();
    this.objectContainer = Db4o.openFile(fileName);
  }

  private void openClient(Map map) throws Db4oIOException, NumberFormatException, OldFormatException, InvalidPasswordException {
    String host = map.get(HOST).toString();
    Integer port = (Integer)map.get(PORT);
    String user = (map.get(USER) != null) ? map.get(USER).toString() : "";
    String password = (map.get(PASSWORD) != null) ? map.get(PASSWORD).toString() : "";

    int portNumber = port;
    this.objectContainer = Db4o.openClient(host, portNumber, user, password);
  }

  private void closeContainer() {
    if( this.objectContainer != null ) {
      this.objectContainer.commit();
      this.objectContainer.close();
    }
  }

  private void deleteValue(Object value) {
    if( this.objectContainer != null ) {
      this.objectContainer.delete(value);
    }
  }

  private void storeValue(Object value) {
    if( this.objectContainer != null ) {
      this.objectContainer.set(value);
    }
  }

  private void querySQL(String query)  {
    if( this.objectContainer != null ) {
        ObjectSetWrapper osw;
      try {
        osw = (ObjectSetWrapper) Sql4o.execute(this.objectContainer, query);
        this.objectSet = osw.ext();
      } catch (SqlParseException ex) {
      } catch (Sql4oException ex) {
      }
    }
  }

  private void querySODA(Object node) {
    if( this.objectContainer != null ) {
      Query query = this.objectContainer.query();

      Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
      item.object = query;
      this.nodeMap.put(node, item);
    }
  }

  private void querySODA(Object node, Object value) {
    if( this.objectContainer != null ) {
      Query query = this.objectContainer.query();
      query.constrain(value);

      Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
      item.object = query;
      this.nodeMap.put(node, item);
    }
  }

  private void executeQuery(Object node) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Query query = (Query) item.object;
    if( query != null ) {
      this.objectSet = query.execute();
    }
  }

  private void addDescend(Object node, Object parent) {

    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = null;

    if( parent.equals(Nodes.OR) || parent.equals(Nodes.AND)) {
      parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(this.rootNode);
    } else {
      parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    }

    if( item != null && parentItem != null ) {
      Query parentQuery = (Query) parentItem.object;
      Query query = parentQuery.descend((String)item.value);
      item.object = query;
      this.nodeMap.put(node, item);
    }
  }

  private void addConstrain(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Query query = (Query) parentItem.object;
      Constraint constraint = query.constrain(item.value);
      item.object = constraint;
      this.nodeMap.put(node, item);

      addToAndOrIfNeeded(node);
    }
  }

  private void addGreater(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.greater();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addSmaller(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.smaller();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addNot(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.not();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addEqual(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.equal();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addLike(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.like();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addContains(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.contains();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addIdentity(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Constraint constraint = parentConstraint.identity();
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addStartsWith(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Boolean value = (Boolean) item.value;
      if( value == null ) {
        value = true;
      }
      Constraint constraint = parentConstraint.startsWith(value.booleanValue());
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addEndsWith(Object node, Object parent) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Constraint parentConstraint = (Constraint) parentItem.object;
      Boolean value = (Boolean) item.value;
      if( value == null ) {
        value = true;
      }
      Constraint constraint = parentConstraint.endsWith(value.booleanValue());
      item.object = constraint;
      this.nodeMap.put(node, item);
    }
  }

  private void addOrder(Object node, Object parent, boolean ascending) {
    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Db4oBuilderItem parentItem = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parent);
    if( item != null && parentItem != null ) {
      Query query = (Query) parentItem.object;
      Query subquery = (ascending)? query.orderAscending() : query.orderDescending();
      item.object = subquery;
      this.nodeMap.put(node, item);
    }
  }

  private void addToAndOrIfNeeded(Object node) {

    Db4oBuilderItem item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(node);
    Constraint constraint = (Constraint) item.object;
    Object parentNode = item.parent;
    while( parentNode != null ) {
      if( parentNode.equals(Nodes.OR) || parentNode.equals(Nodes.AND)) {
        break;
      }
      item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parentNode);
      parentNode = ( item!=null)? item.parent : null;
    }

    if( parentNode != null ) {
      item = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(parentNode);
      Db4oBuilderItem itemParent = (Db4oBuilder.Db4oBuilderItem) this.nodeMap.get(item.parent);
      Constraint constraint2 = (Constraint) itemParent.object;
      Constraint constraint3 = constraint2.or(constraint);
      item.object = constraint3;
    }
  }
  
  private void setSemaphore(String name) {
    if( this.objectContainer != null ) {
      this.semaphoreName = name;
      this.objectContainer.ext().setSemaphore(this.semaphoreName,DEFAULT_SEMAPHORE_WAIT);
    }
  }
  
  private void setSemaphore(Map map) {
    if( this.objectContainer != null && !this.semaphoreSet) {
      this.semaphoreName = map.get(NAME).toString();
      int waitTime = (Integer)map.get(WAIT);
      this.semaphoreSet = this.objectContainer.ext().setSemaphore(this.semaphoreName, waitTime);
      
    }
  }

  private void releaseSemaphore() {
    if( this.objectContainer != null && this.semaphoreSet) {
      this.objectContainer.ext().releaseSemaphore(this.semaphoreName);
      this.semaphoreSet = false;
    }
  }
  
  private void setConfig() {
	this.config = Db4o.configure();	  
	DiagnosticConfiguration diagnosticConfig = this.config.diagnostic();
	FreespaceConfiguration freespaceConfig = this.config.freespace();
	QueryConfiguration queryConfig = this.config.queries();
  }
  
  private void setConfig(Map map) {
	this.config = Db4o.configure();	  
		
    if( map.containsKey( Config.ACTIVATION_DEPTH ) ) {
	  config.activationDepth((Integer)map.get( Config.ACTIVATION_DEPTH ));  
    }
    if( map.containsKey( Config.ALLOW_VERSION_UPDATE ) ) {
	  config.allowVersionUpdates((Boolean)map.get(Config.ALLOW_VERSION_UPDATE));  
	}
    if( map.containsKey( Config.AUTOMATIC_SHUTDOWN ) ) {
  	  config.automaticShutDown((Boolean)map.get(Config.AUTOMATIC_SHUTDOWN ));  
  	}
    if( map.containsKey( Config.BLOCK_SIZE ) ) {
      config.blockSize((Integer)map.get(Config.BLOCK_SIZE ));  
    }
    if( map.containsKey( Config.BTREE_CACHE_HEIGHT ) ) {
      config.bTreeCacheHeight((Integer)map.get(Config.BTREE_CACHE_HEIGHT ));  
    }
    if( map.containsKey( Config.BTREE_NODE_SIZE ) ) {
      config.bTreeNodeSize((Integer)map.get(Config.BTREE_NODE_SIZE ));  
    }
    if( map.containsKey( Config.CALLBACKS ) ) {
      config.callbacks((Boolean)map.get(Config.CALLBACKS ));  
    }
    if( map.containsKey( Config.CALL_CONSTRUCTORS ) ) {
      config.callConstructors((Boolean)map.get(Config.CALL_CONSTRUCTORS ));  
    }
    if( map.containsKey( Config.DETECT_SCHEMA_CHANGES ) ) {
      config.detectSchemaChanges((Boolean)map.get(Config.DETECT_SCHEMA_CHANGES ));  
    }
    if( map.containsKey( Config.EXCEPTION_ON_NOT_STORABLE ) ) {
      config.exceptionsOnNotStorable((Boolean)map.get(Config.EXCEPTION_ON_NOT_STORABLE ));  
    }
    if( map.containsKey( Config.FLUSH_FILE_BUFFERS ) ) {
      config.flushFileBuffers((Boolean)map.get(Config.FLUSH_FILE_BUFFERS ));  
    }
    if( map.containsKey( Config.GENERATE_UUIDS ) ) {
      config.generateUUIDs((ConfigScope)map.get(Config.GENERATE_UUIDS ));  
    }
    if( map.containsKey( Config.GENERATE_VERSION_NUMBERS ) ) {
      config.generateVersionNumbers((ConfigScope)map.get(Config.GENERATE_VERSION_NUMBERS ));  
    }
    if( map.containsKey( Config.INTERN_STRINGS ) ) {
      config.internStrings((Boolean)map.get(Config.INTERN_STRINGS ));  
    }
    if( map.containsKey( Config.IO_ADAPTER ) ) {
      config.io((IoAdapter)map.get(Config.IO_ADAPTER ));  
    }
    if( map.containsKey( Config.LOCK_DATABASE_FILE ) ) {
      config.lockDatabaseFile((Boolean)map.get(Config.LOCK_DATABASE_FILE ));  
    }
    if( map.containsKey( Config.MARK_TRANSIENT ) ) {
      config.markTransient((String)map.get(Config.MARK_TRANSIENT ));  
    }
    if( map.containsKey( Config.MESSAGE_LEVEL ) ) {
      config.messageLevel((Integer)map.get(Config.MESSAGE_LEVEL ));  
    }
    if( map.containsKey( Config.OPTIMIZE_NATIVEQUERIES ) ) {
      config.optimizeNativeQueries((Boolean)map.get(Config.OPTIMIZE_NATIVEQUERIES ));  
    }
    if( map.containsKey( Config.REFLECT_WITH ) ) {
      config.reflectWith((Reflector)map.get(Config.REFLECT_WITH ));  
    }
    if( map.containsKey( Config.SET_OUT ) ) {
      config.setOut((PrintStream)map.get(Config.SET_OUT ));  
    }
    if( map.containsKey( Config.UNICODE ) ) {
      config.unicode((Boolean)map.get(Config.UNICODE ));  
    }
    if( map.containsKey( Config.UPDATE_DEPTH ) ) {
      config.updateDepth((Integer)map.get(Config.UPDATE_DEPTH ));  
    }
  }

}
